home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume5 / dither < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  12.0 KB

  1. Subject: Color Dither (ver 1.1)
  2. Newsgroups: mod.sources
  3. Approved: jpn@panda.UUCP
  4.  
  5. Mod.sources:  Volume 5, Issue 3
  6. Submitted by: talcott!seismo!s3sun!sdcsvax!hutch (Jim Hutchison)
  7.  
  8.  
  9. This works well on a sun, it converts 24bit images stored in
  10. 3 files into a screen image.
  11.  
  12. The usage is: display filename [wide [high]]
  13.  
  14. "filename" is assumed to be a name for 3 files filename{R,G,B} The
  15. default width is set to 512.  The path has a maximum length(1024
  16. currently).  Height defaults to width unless specified.  The program
  17. can be configured for various color limitations (and has been tested at
  18. 1/1/1, 2/2/1, and 3/3/2 bits of RGB) this fits in with some rgb
  19. printers, the Amiga, and the Sun color frame buffer respectively.
  20.  
  21. This code was posted to net.sources a few weeks ago, but has improved
  22. in usability and readability since then (not to mention speed and
  23. configurability).
  24.  
  25.         Jim Hutchison    hutch@sdcsvax.UUCP
  26.  
  27. #! /bin/sh
  28. # This is a shell archive, meaning:
  29. # 1. Remove everything above the #! /bin/sh line.
  30. # 2. Save the resulting text in a file.
  31. # 3. Execute the file with /bin/sh (not csh) to create:
  32. #    tcd.c
  33. # This archive created: Tue May 13 03:36:33 1986
  34. export PATH; PATH=/bin:/usr/bin:$PATH
  35. if test -f 'tcd.c'
  36. then
  37.     echo shar: "will not over-write existing file 'tcd.c'"
  38. else
  39. cat << \SHAR_EOF > 'tcd.c'
  40. #include <stdio.h>
  41. #include <sys/file.h>
  42. #include <pixrect/pixrect_hs.h>
  43.  
  44. /*
  45.  *    Dither!  Color dither a U.S.C. tape image.
  46.  *
  47.  *    Original Tape code by Brian Kantor.
  48.  *
  49.  *    The dithering is the product of madness and extrapolation
  50.  *    from the concepts employed for black and white dithers,
  51.  *    Jim Hutchison. Presumes 8bit bytes.
  52.  */
  53.  
  54. #define LARGEST        (0xff)            /* 8 bits per color */
  55. #define UNUSED_BITS    0            /* unused bits      */
  56.  
  57. #define R_BITS        3            /* Bits of red               */
  58. #define R_ERR        (8 - R_BITS)        /* Bits of error, from true  */
  59. #define R_SHIFT        (8 - R_BITS)        /* shift to get usefull bits */
  60. #define R_MASK        (LARGEST >> R_BITS)    /* masked off bits           */
  61. #define R_NEXT        (R_MASK - 1)        /* base_color + next = left  */
  62. #define R_TOP        (LARGEST & ~R_MASK)    /* maximal value, red        */
  63. #define R_NVAL        (LARGEST >> R_SHIFT)    /* shades of red + black     */
  64. #define R_MAP        0x07            /* mask to get color table   */
  65.  
  66. #define G_BITS        3            /* Bits of green             */
  67. #define G_ERR        (8 - G_BITS)        /* Bits of error, from true  */
  68. #define G_SHIFT        (8 - G_BITS)        /* shift to get usefull bits */
  69. #define G_MASK        (LARGEST >> G_BITS)    /* masked off bits           */
  70. #define G_NEXT        (G_MASK - 1)        /* base_color + next = left  */
  71. #define G_TOP        (LARGEST & ~G_MASK)    /* maximal value, green      */
  72. #define G_NVAL        (LARGEST >> G_SHIFT)    /* shades of green + black   */
  73. #define G_MAP        (0x07 << 3)        /* mask to get color table   */
  74.  
  75. #define B_BITS        2            /* Bits of blue              */
  76. #define B_ERR        (8 - B_BITS)        /* Bits of error, from true  */
  77. #define B_SHIFT        (8 - B_BITS)        /* shift to get usefull bits */
  78. #define B_MASK        (LARGEST >> B_BITS)    /* masked off bits           */
  79. #define B_NEXT        (B_MASK - 1)        /* base_color + next = left  */
  80. #define B_TOP        (LARGEST & ~B_MASK)    /* maximal value, blue       */
  81. #define B_NVAL        (LARGEST >> B_SHIFT)    /* shades of blue + black    */
  82. #define B_MAP        (0x03 << 6)        /* mask to get color table   */
  83.  
  84. /*
  85.  *    2(4(8)) by 2(4(8)) ordered dither, it all hinges on this dither,
  86.  *    and the color-table.  Note that dithers larger than 4x4
  87.  *    require changes in lower code.
  88.  */
  89.  
  90. #ifdef    LARGE_DITHER
  91.  
  92. #define DSIZE        4    /* must be a power of 2 */
  93. #define DITH_LOG    4    /* log[2](DSIZE*DSIZE) */
  94. #define DMASK        DSIZE-1    /* Dither mask to get position in dither */
  95.  
  96. short dither[DSIZE][DSIZE] = {
  97.     0,    8,    3,    11,
  98.     12,    4,    15,    7,
  99.     2,    10,    1,    9,
  100.     14,    6,    13,    5
  101. };
  102.  
  103. #else    /* LARGE_DITHER */
  104.  
  105. #define DSIZE        2    /* must be a power of 2 */
  106. #define DITH_LOG    2    /* log[2](DSIZE*DSIZE) */
  107. #define DMASK        DSIZE-1    /* Dither mask to get position in dither */
  108.  
  109. short dither[DSIZE][DSIZE] = {
  110.     0,    3,
  111.     2,  1
  112. };
  113.  
  114. #endif    /* LARGE_DITHER */
  115.  
  116. /* Huge dither to use with the 2 bit color, blue
  117. */
  118. #ifdef    BLUE_DITHER
  119.  
  120. #define BDSIZE        8    /* must be a power of 2 */
  121. #define BDITH_LOG    6    /* log[2](BDSIZE*BDSIZE) */
  122. #define BDMASK        BDSIZE-1/* Dither mask to get position in dither */
  123.  
  124. short bdither[BDSIZE][BDSIZE] = {
  125.     0,    32,    12,    44,    3,    35,    15,    47,
  126.     48,    16,    60,    28,    51,    19,    63,    31,
  127.     8,    40,    4,    36,    11,    43,    7,    39,
  128.     56,    24,    52,    20,    59,    27,    55,    23,
  129.     2,    34,    14,    46,    1,    33,    13,    45,
  130.     50,    18,    62,    30,    49,    17,    61,    29,
  131.     10,    42,    6,    38,    9,    41,    5,    37,
  132.     58,    26,    54,    22,    57,    25,    53,    21
  133. };
  134.  
  135. #else    /* BLUE_DITHER */
  136. #define BDITH_LOG    DITH_LOG
  137. #endif    /* BLUE_DITHER */
  138.  
  139. /*
  140.  * Determine if we have more error than we have dither, and
  141.  * give the number of bits we shall have to shift down.
  142.  */
  143. #if (R_ERR - DITH_LOG) > 0
  144. #define R_ISHIFT    (R_ERR - DITH_LOG)
  145. #else
  146. #define R_ISHIFT    (0)
  147. #endif
  148.  
  149. #if (G_ERR - DITH_LOG) > 0
  150. #define G_ISHIFT    (G_ERR - DITH_LOG)
  151. #else
  152. #define G_ISHIFT    (0)
  153. #endif
  154.  
  155. #if (B_ERR - BDITH_LOG) > 0
  156. #define B_ISHIFT    (B_ERR - BDITH_LOG)
  157. #else
  158. #define B_ISHIFT    (0)
  159. #endif
  160.  
  161. /*
  162.  * Image/colormap definitions.
  163.  */
  164. #define    MAPSIZE        256            /* size of pallet     */
  165. #define    COLORS        256            /* number of colors   */
  166. #define IMAGESIZE    512            /* size of tape image */
  167. #define IMAGE_VOL    (IMAGESIZE*IMAGESIZE)    /* volume of image    */
  168.  
  169. #define MAXPATH        1024            /* max length of filename */
  170.  
  171. struct pixrect *display;
  172. struct pixrect *memory_frame;
  173.  
  174. /* for palette (sun) generation */
  175.  
  176. unsigned char red[MAPSIZE], grn[MAPSIZE], blu[MAPSIZE];
  177.  
  178. /* shade tables (for speed) */
  179.  
  180. static unsigned int r_base_right[COLORS];
  181. static unsigned int r_base_left[COLORS];
  182. static unsigned int r_dval[COLORS];
  183.  
  184. static unsigned char g_base_right[COLORS];
  185. static unsigned char g_base_left[COLORS];
  186. static unsigned char g_dval[COLORS];
  187.  
  188. static unsigned char b_base_right[COLORS];
  189. static unsigned char b_base_left[COLORS];
  190. static unsigned char b_dval[COLORS];
  191.  
  192. /* nasty procedures */
  193. int
  194. min(a,b)
  195.     int a,b;
  196. {
  197.     return((a > b)? b : a);
  198. }
  199.  
  200. int
  201. max(a,b)
  202.     int a,b;
  203. {
  204.     return((a > b)? a : b);
  205. }
  206.  
  207. main(argc,argv)
  208.     int argc;
  209.     char **argv;
  210. {
  211.     register unsigned int color, dith_value;
  212.     register unsigned int r_color, g_color, b_color;
  213.     register unsigned char *pr, *pg, *pb;
  214.  
  215. #ifdef    BLUE_DITHER
  216.     unsigned int b_dith_value;
  217. #endif    /* BLUE_DITHER */
  218.  
  219.     int x_imagesize, y_imagesize, image_vol;
  220.  
  221.     int fr, fg, fb;
  222.     int i, plen;
  223.     int x, y;
  224.     char buf[MAXPATH];
  225.     unsigned char *picture, *pict_row;    /* keep row to avoid padding problems */
  226.     int row_bytes;            /* bytes per scan-line */
  227.  
  228.     if (argc < 2) {
  229.     fprintf(stderr, "Usage: %s rgb-imagefile [hsize] [vsize]\n", argv[0]);
  230.     exit(-1);
  231.     }
  232.  
  233.     if (argc > 2) {
  234.     x_imagesize = atoi(argv[2]);
  235.  
  236.     if (argc > 3) {
  237.         y_imagesize = atoi(argv[3]);
  238.     } else {
  239.         y_imagesize = x_imagesize;
  240.     }
  241.  
  242.     image_vol = y_imagesize * x_imagesize;
  243.  
  244.     pr = (unsigned char *) malloc(image_vol * sizeof(unsigned char));
  245.     pg = (unsigned char *) malloc(image_vol * sizeof(unsigned char));
  246.     pb = (unsigned char *) malloc(image_vol * sizeof(unsigned char));
  247.     } else {
  248.     x_imagesize = y_imagesize = IMAGESIZE;
  249.     pr = (unsigned char *) malloc(IMAGE_VOL);
  250.     pg = (unsigned char *) malloc(IMAGE_VOL);
  251.     pb = (unsigned char *) malloc(IMAGE_VOL);
  252.     image_vol = IMAGE_VOL;
  253.     }
  254.  
  255.     printf("high %d wide %d vol %d\n", y_imagesize, x_imagesize, image_vol);
  256.  
  257.     strcpy(buf,argv[1]);
  258.     plen = strlen(buf);
  259.     buf[plen] = 'R';
  260.     fr = open(buf, O_RDONLY, 0444);
  261.     if (fr < 0) {
  262.     perror(buf);
  263.     exit(1);
  264.     }
  265.  
  266.     buf[plen] = 'G';
  267.     fg = open(buf, O_RDONLY, 0444);
  268.     if (fg == 0) {
  269.     perror(buf);
  270.     exit(1);
  271.     }
  272.  
  273.     buf[plen] = 'B';
  274.     fb = open(buf, O_RDONLY, 0444);
  275.     if (fb < 0) {
  276.     perror(buf);
  277.     exit(1);
  278.     }
  279.  
  280.     display = pr_open("/dev/cgone0");
  281.     if (display == NULL) {
  282.     fprintf(stderr,"Color Display not available, sorry\n");
  283.     exit (-1);
  284.     }
  285.  
  286.     puts("Reading RGB files");
  287.  
  288.     if (read(fr, pr, image_vol) <= 0)
  289.         perror("red");
  290.     if (read(fg, pg, image_vol) <= 0)
  291.         perror("grn");
  292.     if (read(fb, pb, image_vol) <= 0)
  293.         perror("blu");
  294.  
  295.     puts("Creating memory pixrect");
  296.  
  297.     /* Get a pointer to a memory pixrect */
  298.     memory_frame = mem_create(x_imagesize, y_imagesize, 8);
  299.  
  300.     /* Get a pointer to the image buffer associated with the memory pixrect */
  301.     pict_row = picture = (unsigned char *) mpr_d(memory_frame)->md_image;
  302.  
  303.     /* Get bytes per scan-line (note that padding exists) */
  304.     row_bytes = mpr_d(memory_frame)->md_linebytes;
  305.  
  306.     puts("Initializing tables");
  307.  
  308.     init_tables();
  309.  
  310.     puts("Processing image");
  311.  
  312.     for (y = 0; y < y_imagesize; y++, picture = pict_row += row_bytes) {
  313.     for (x = 0; x < x_imagesize; x++) {
  314.  
  315.         r_color = *pr++;
  316.         g_color = *pg++;
  317.         b_color = *pb++;
  318.  
  319. #ifdef    BLUE_DITHER
  320.         b_dith_value = bdither[x & BDMASK][y & BDMASK];
  321. #endif    /* BLUE_DITHER */
  322.  
  323.         dith_value = dither[x & DMASK][y & DMASK];
  324.  
  325.         if (r_dval[r_color] > dith_value)
  326.         color = r_base_left[r_color];
  327.         else
  328.         color = r_base_right[r_color];
  329.  
  330.         if (g_dval[g_color] > dith_value)
  331.         color |= g_base_left[g_color];
  332.         else
  333.         color |= g_base_right[g_color];
  334.  
  335. #ifdef    BLUE_DITHER
  336.         if (b_dval[b_color] > b_dith_value)
  337. #else
  338.         if (b_dval[b_color] > dith_value)
  339. #endif    /* BLUE_DITHER */
  340.         color |= b_base_left[b_color];
  341.         else
  342.         color |= b_base_right[b_color];
  343.  
  344.         *picture++ = color;
  345.     }
  346.     }
  347.  
  348.     /*
  349.      *    Generate colormap with (cycle is 8 values):
  350.      *        32  cycles of red
  351.      *        1   cycle  of green
  352.      *        1/2 cycle  of blue
  353.      *    all varying smoothely, note that an improved
  354.      *    map which employs better graduation of color
  355.      *    can be employed, but on our interlaced monitor
  356.      *    this caused an extremely painful flicker.
  357.      */
  358.  
  359.     puts("Building color lookup table");
  360.  
  361.     for (i=0; i < MAPSIZE; i++) {
  362.     red[i] = (i & R_MAP) << R_SHIFT;
  363.     grn[i] = (i & G_MAP) << (G_SHIFT - R_BITS);
  364.     blu[i] = (i & B_MAP) << (B_SHIFT - R_BITS - G_BITS);
  365.     }
  366.  
  367.     pr_putcolormap(display, 0, MAPSIZE, red, grn, blu);
  368.  
  369.     /* copy the complete image to the display, center it also.
  370.     */
  371.  
  372.     puts("Displaying");
  373.  
  374.     pr_rop(display,
  375.        max((display->pr_width - x_imagesize) >> 1, 0),
  376.        max((display->pr_height - y_imagesize) >> 1,0),
  377.        min(display->pr_width, x_imagesize),
  378.        min(display->pr_height, y_imagesize),
  379.        (PIX_SRC|PIX_DONTCLIP), memory_frame, 0, 0);
  380.  
  381.     pr_close(display);
  382.     close(fr);
  383.     close(fg);
  384.     close(fb);
  385. }
  386.  
  387. init_tables()
  388. {
  389.     register unsigned int intensity, i;
  390.     register double true_i;
  391.     register double rfactor, gfactor, bfactor;
  392.  
  393.     rfactor = ((double)R_NVAL) / ((double)R_NVAL+1);
  394.     gfactor = ((double)G_NVAL) / ((double)G_NVAL+1);
  395.     bfactor = ((double)B_NVAL) / ((double)B_NVAL+1);
  396.  
  397.     for (i = 0; i < 256; i++) {
  398.     true_i = (double) i;
  399.  
  400.     /*
  401.      * scale color to fit inside of range
  402.      * calculate right base shade by trimming off error.
  403.      */
  404.     intensity = (unsigned int)(true_i * rfactor);
  405.     r_base_right[i] = intensity & ~R_MASK;
  406.  
  407.     if (r_base_right[i] != R_TOP) {
  408.         r_dval[i] = (intensity & R_MASK) >> R_ISHIFT;
  409.         r_base_left[i] =
  410.         ((intensity + R_NEXT) & R_TOP) >> (UNUSED_BITS+G_BITS+B_BITS);
  411.     } else
  412.         r_dval[i] = 0;
  413.  
  414.     r_base_right[i] >>= (UNUSED_BITS + G_BITS + B_BITS);
  415.  
  416.     /*
  417.      * scale color to fit inside of range
  418.      * calculate right base shade by trimming off error.
  419.      */
  420.     intensity = (unsigned int)(true_i * gfactor);
  421.     g_base_right[i] = intensity & ~G_MASK;
  422.  
  423.     if (g_base_right[i] != G_TOP) {
  424.         g_dval[i] = (intensity & G_MASK) >> G_ISHIFT;
  425.         g_base_left[i] =
  426.         ((intensity + G_NEXT) & G_TOP) >> (UNUSED_BITS + B_BITS);
  427.     } else
  428.         g_dval[i] = 0;
  429.  
  430.     g_base_right[i] >>= (UNUSED_BITS + B_BITS);
  431.  
  432.     /*
  433.      * scale color to fit inside of range
  434.      * calculate right base shade by trimming off error.
  435.      */
  436.     intensity = (unsigned int)(true_i * bfactor);
  437.     b_base_right[i] = intensity & ~B_MASK;
  438.  
  439.     if (b_base_right[i] != B_TOP) {
  440.         b_dval[i] = (intensity & B_MASK) >> B_ISHIFT;
  441.         b_base_left[i] =
  442.         ((intensity + B_NEXT) & B_TOP) >> UNUSED_BITS;
  443.     } else
  444.         b_dval[i] = 0;
  445.  
  446.     b_base_right[i] >>= UNUSED_BITS;
  447.     }
  448. }
  449. SHAR_EOF
  450. fi
  451. if test -f 'Makefile'
  452. then
  453.     echo shar: "will not over-write existing file 'Makefile'"
  454. else
  455. cat << \SHAR_EOF > 'Makefile'
  456. #
  457. #    Makefile for tcd (Tape color dither)
  458. #
  459. CC    = /bin/cc
  460. CFLAGS    = -O
  461.  
  462. tcd: tcd.c
  463.     $(CC) $(CFLAGS) -o $@ tcd.c -lpixrect
  464.  
  465. clean:
  466.     rm -f tcd.o
  467. SHAR_EOF
  468. fi
  469. exit 0
  470. #    End of shell archive
  471.  
  472.